package com.hqd.ch03.v16.aop.framework;

import com.hqd.ch03.v16.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInvocation;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 连接点类，用以执行通知及目标方法
 */
public class ReflectiveMethodInvocation implements MethodInvocation {
    private Object proxy;
    private Method method;
    private Object[] args;
    private List<MethodInterceptor> mis;
    private int currentInterceptorIndex = -1;

    public ReflectiveMethodInvocation(Object proxy, Method method,
                                      Object[] args, List<MethodInterceptor> mis) {
        this.proxy = proxy;
        this.method = method;
        this.args = args;
        this.mis = mis;
    }

    @Nonnull
    @Override
    public Method getMethod() {
        return method;
    }

    @Nonnull
    @Override
    public Object[] getArguments() {
        return args;
    }

    @Nullable
    @Override
    public Object proceed() throws Throwable {
        /**
         * 链式调用通知
         */
        if (mis.size() - 1 == currentInterceptorIndex) {
            return getMethod().invoke(proxy, args);
        }
        MethodInterceptor methodInterceptor = this.mis.get(++currentInterceptorIndex);

        return methodInterceptor.invoke(this);
    }

    @Nullable
    @Override
    public Object getThis() {
        return proxy;
    }

    @Nonnull
    @Override
    public AccessibleObject getStaticPart() {
        return null;
    }
}
